//
//  User.swift
//  
//
//  Created by Jiang Chencheng on 2024/8/30.
//

import Vapor
import Fluent
import struct Foundation.UUID

enum Mood: String, Codable {
    case `default`
    case ralxed
    case calm
    case amazing
}

final class User: Model, @unchecked Sendable {
    static let schema = "user"
    
    @ID(key: .id)
    var id: UUID?
    
    @Field(key: "nickname")
    var nickname: String
    
    @Field(key: "email")
    var email: String
    
    @OptionalEnum(key: "mood")
    var mood: Mood?
    
    @Field(key: "pair_code")
    var pairCode: String
    
    @Field(key: "password")
    var password: String
    
    @Timestamp(key: "created_at", on: .create)
    var createdAt: Date?

    @Timestamp(key: "updated_at", on: .update)
    var updatedAt: Date?
    
    @Timestamp(key: "deleted_at", on: .delete)
    var deletedAt: Date?
    
    init() { }

    init(id: UUID? = nil, nickname: String = "", email: String, password: String) {
        self.id = id
        self.nickname = nickname
        self.mood = .default
        self.email = email
        self.password = password
        self.pairCode = String.random(with: 6)
    }
    
    func toDTO() -> UserDTO {
        .init(
            id: self.id,
            nickname: self.nickname,
            email: self.email,
            mood: self.mood,
            pairCode: self.pairCode
        )
    }
    
    static func query(on db: any Database, userID: UUID) async throws -> User {
        guard let user = try await User.query(on: db)
            .filter(\.$id == userID)
            .first() 
        else {
            throw BizError.userNotFound
        }
        return user
    }
    
    static func query(on db: any Database, email: String) async throws -> User {
        guard let user = try await User.query(on: db)
            .filter(\.$email == email)
            .first() 
        else {
            throw BizError.userNotFound
        }
        return user
    }
    
    static func query(on db: any Database, pairCode: String) async throws -> User {
        guard let user = try await User.query(on: db)
            .filter(\.$pairCode == pairCode)
            .first()
        else {
            throw BizError.userNotFound
        }
        return user
    }
}


